<template>
  <div v-if="title || (tableOperaColumn && tableOperaColumn.length)" class="table-toolbar">
    <!-- 顶部左侧区域 -->
    <div class="flex items-center table-toolbar-left">
      <div class="table-toolbar-left-title">
        {{ title }}
        <n-tooltip v-if="titleTooltip" trigger="hover">
          <template #trigger>
            <n-icon size="18" class="ml-1 text-gray-400 cursor-pointer">
              <QuestionCircleOutlined />
            </n-icon>
          </template>
          {{ titleTooltip }}
        </n-tooltip>
      </div>
      <template v-if="tableOperaColumn && tableOperaColumn.length">
        <n-space>
          <n-button
            v-for="(item, key) in tableOperaColumn"
            :key="key"
            class="bnt-list"
            :class="{ printActive: item.prop === 'print' }"
            v-bind="item.bind"
            :type="key === 0 ? 'primary' : item.bind.type ? item.bind.type : 'default'"
          >
            <template #icon>
              <DFSvgIcon v-if="item.svg" class="print-svg" :name="item.svg" />
              <i v-if="item.prop === 'add'" class="iconfont icon-jiahao" />
              <!-- <i v-if="item.iconfont" class="iconfont" :class="item.iconfont"></i> -->
              <i
                v-else-if="item.prop === 'delete'"
                class="iconfont icon-shanchu"
                style="font-size: 14px"
              />

              <n-icon v-else-if="item.icon" :component="item.icon" />

              <i v-else-if="item.prop === 'import'" class="iconfont icon-daoruicon" />

              <i v-else-if="item.prop === 'export'" class="iconfont icon-daochuicon" />
              <DFSvgIcon v-else-if="item.prop === 'print'" class="print-svg" name="print" />
              <!-- <i v-else-if="item.prop === 'print'" class="iconfont icon-d-print"></i> -->
            </template>

            {{ $t(`common.button.${item.label || item.prop}`) }}
          </n-button>
        </n-space>
      </template>
      <slot name="tableTitle" />
    </div>

    <div v-if="toolbarRight" class="flex items-center table-toolbar-right">
      <!-- 顶部右侧区域 -->
      <slot name="toolbar" />

      <!-- 刷新 -->
      <!-- <n-tooltip trigger="hover">
        <template #trigger>
          <div class="table-toolbar-right-icon" @click="reload">
            <n-icon size="18">
              <ReloadOutlined />
            </n-icon>
          </div>
        </template>
        <span>{{ $t('common.table.refresh') }}</span>
      </n-tooltip> -->

      <!-- 密度 -->
      <!-- <n-tooltip trigger="hover">
        <template #trigger>
          <div class="table-toolbar-right-icon">
            <n-dropdown
              @select="densitySelect"
              trigger="click"
              :options="densityOptions"
              v-model:value="tableSize"
            >
              <n-icon size="18">
                <ColumnHeightOutlined />
              </n-icon>
            </n-dropdown>
          </div>
        </template>
        <span>{{ $t('common.table.density') }}</span>
      </n-tooltip> -->

      <!-- 表格设置单独抽离成组件 -->
      <!-- <ColumnSetting :hasSelection="hasSelection" :routeName="routeName" /> -->
    </div>
  </div>
  <div class="s-table">
    <n-data-table
      ref="tableElRef"
      v-bind="getBindValues"
      :pagination="pagination"
      :titleAlign="titleAlign"
      :align="align"
      @update:page="updatePage"
      @update:page-size="updatePageSize"
      @update:sorter="handleSorterChange"
      @update:checked-row-keys="handleCheckedRowKeysChangeFn"
    >
      <template v-for="item in Object.keys($slots)" #[item]="data" :key="item">
        <slot :name="item" v-bind="data" />
      </template>
      <template #empty>
        <NEmpty :description="$t('common.table.noData')">
          <template #icon>
            <img src="@/assets/svg/empty.svg" />
          </template>
        </NEmpty>
      </template>
      <!-- <template #empty>
        <n-empty :description="$t('common.table.noData')" />
      </template> -->
    </n-data-table>

    <FixedModal
      v-if="isGetFieldInfo"
      ref="fixedModal"
      :table-context="tableContext"
      :set-field-info-list-fn="setFieldInfoList"
      @get-field-info-list-fn="getFieldInfoListFn"
    />
  </div>
</template>

<script lang="ts">
  import {
    ref,
    // defineComponent,
    reactive,
    unref,
    toRaw,
    computed,
    toRefs,
    onMounted,
    nextTick,
  } from 'vue';
  import { NEmpty } from 'naive-ui';
  import { useRoute } from 'vue-router';
  import {
    // ReloadOutlined,
    // ColumnHeightOutlined,
    QuestionCircleOutlined,
  } from '@vicons/antd';

  import { cloneDeep } from 'lodash-es';
  import { createTableContext } from './hooks/useTableContext';

  // import ColumnSetting from './components/settings/ColumnSetting.vue';

  import { useLoading } from './hooks/useLoading';
  import { useColumns } from './hooks/useColumns';
  import { useDataSource } from './hooks/useDataSource';
  import { usePagination } from './hooks/usePagination';
  import { basicProps } from './props';
  import type { BasicTableProps } from './types/table';
  import FixedModal from './components/FixedModal.vue';
  import { useMixins } from '@/hooks/useMixins';

  import { getViewportOffset } from '@/utils/domUtils';
  import { useWindowSizeFn } from '@/hooks/event/useWindowSizeFn';
  import { isBoolean } from '@/utils/is';

  // import importImg from '@/assets/images/importImg.svg';
  // import exportImg from '@/assets/images/exportImg.svg';

  import { t } from '@/i18n';

  import { usePermission } from '@/hooks/web/usePermission';

  export default {
    components: {
      // ReloadOutlined,
      // ColumnHeightOutlined,
      // ColumnSetting,
      QuestionCircleOutlined,
      NEmpty,
      FixedModal,
    },
    props: {
      ...basicProps,
      hasSelection: {
        type: Boolean,
        default: false,
      },
      isGetFieldInfo: {
        type: Boolean,
        default: false,
      },
      getFieldInfoList: {
        type: Function,
        default: () => {},
      },
      setFieldInfoList: {
        type: Function,
        default: () => {},
      },
      showAddAndDelBtn: {
        type: Boolean,
        default: () => true,
      },
      titleAlign: {
        type: String,
        default: 'left',
      },
      align: {
        type: String,
        default: 'left',
      },
    },
    emits: [
      'fetch-success',
      'fetch-error',
      'update:checked-row-keys',
      'edit-end',
      'edit-cancel',
      'edit-row-end',
      'edit-change',
      'updateCheck',
      'changePage',
      'clearRowKeysFn',
      'editTableDataChangeFn'
    ],
    setup(props, { emit }) {
      const { hasPermission } = usePermission();

      const { routerType } = useMixins();

      const loading2 = ref(false);

      const fieldInfoList = ref([]);

      const isGetFieldInfoListFn: any = ref(false);

      const fixedModal: any = ref(null);

      const route: any = toRaw(useRoute());

      const { meta = {} }: any = route;

      const { authCode = '' } = meta;

      const deviceHeight = ref(150);
      const tableElRef: any = ref<ComponentRef>(null);
      const wrapRef = ref<Nullable<HTMLDivElement>>(null);
      let paginationEl: HTMLElement | null;

      const tableData: any = ref<Recordable[]>([]);
      const innerPropsRef = ref<Partial<BasicTableProps>>();

      const getProps: any = computed(() => {
        return { ...props, ...unref(innerPropsRef) } as BasicTableProps;
      });

      const clearSorter = () => {
        tableElRef.value.sort(null);
      };
      // const importImage:any =ref('')
      const { getLoading, setLoading } = useLoading(getProps);

      const { getPaginationInfo, setPagination } = usePagination(getProps);

      function clearcheckedRowKeysFn(delList: any = []) {
        if (delList && delList.length) {
          checkedRowKeys.value = checkedRowKeys.value.filter((item: any) =>
            delList.includes(item[getBindValues.value.rowKey])
          );
        }
      }

      const {
        getDataSourceRef,
        getDataSource,
        getRowKey,
        reload,
        setSorterOption,
        setTableData,
        editTableHandleAddFn,
        getCurentPageDataFn,
        editTableHandleDeleteFn,
        setEditTableDataFn,
        getEditTableDataFn,
        setEditTableAllDataFn,
      } = useDataSource(
        getProps,
        {
          getPaginationInfo,
          setPagination,
          tableData,
          setLoading,
          clearSorter,
          clearcheckedRowKeysFn,
        },
        emit
      );

      const tableContext: any = useColumns(
        getProps,
        fixedModal,
        editTableHandleDeleteFn,
        routerType
      );

      const {
        getPageColumns,
        setColumns,
        setColumns2,
        getColumns,
        getCacheColumns,
        setCacheColumnsField,
      } = tableContext;

      const state = reactive({
        tableSize: unref(getProps as any).size || 'medium',
        isColumnSetting: false,
      });

      const handleSorterChange = (options) => {
        setSorterOption(options);
      };

      const checkedRowKeys: any = ref([]);

      const clearRowKeysFn = () => {
        checkedRowKeys.value = [];
      };

      const clearCheckedRowKeysFn = (value) => {
        checkedRowKeys.value = [];
        checkedRowKeys.value = [value];
      };

      const densityOptions = [
        {
          type: 'menu',
          label: t('common.table.small'),
          key: 'small',
        },
        {
          type: 'menu',
          label: t('common.table.medium'),
          key: 'medium',
        },
        {
          type: 'menu',
          label: t('common.table.large'),
          key: 'large',
        },
      ];

      // 页码切换
      function updatePage(page) {
        // console.log(page);

        setPagination({ page });
        emit('changePage', page);
        reload();

        if (props.isEditTable) getCurentPageDataFn();
      }

      // 分页数量切换
      function updatePageSize(size) {
        setPagination({ page: 1, pageSize: size });
        reload();

        if (props.isEditTable) getCurentPageDataFn();
      }

      // 分页数量切换
      // function updatePageNum(size) {
      //   console.log(111);
      //   console.log(size);
      //   reload();
      //   setPagination({ page: 1, pageSize: size });

      //   if (props.isEditTable) {
      //     getCurentPageDataFn();
      //   }
      // }
      // 密度切换
      function densitySelect(e) {
        state.tableSize = e;
      }

      // 选中行
      // function updateCheckedRowKeys(rowKeys) {
      //   emit('update:checked-row-keys', rowKeys);
      // }
      // importImage.value = computed(() => {
      //   return importImg
      // })
      // 获取表格大小
      const getTableSize = computed(() => state.tableSize);

      const setTableTitleFn = (item = null) => {
        let fixed: any;

        if (item) {
          const { fixedPosition = 0 } = item;

          switch (Number(fixedPosition)) {
            case 1:
              fixed = 'left';
              break;

            case 2:
              fixed = 'right';
              break;

            default:
              break;
          }
        }

        return fixed;
      };

      const getFieldInfoListFn = async () => {
        isGetFieldInfoListFn.value = true;

        loading2.value = true;

        try {
          const res = await props.getFieldInfoList({
            url: route.fullPath,
          });

          const { data: row = [] } = res;

          if (row && row.length) {
            const tableTitle: any = getColumns();

            const selection = tableTitle.find((item) => item.key === 'selection');

            let newTableTitle: any = [];

            const leftTableTitle: any = [];

            const rightTableTitle: any = [];

            row
              .sort((a, b) => a.fieldOrder - b.fieldOrder)
              .forEach((item) => {
                const { field = '', selected = 0, fixedPosition = 0, fieldOrder = 0 } = item;

                if (field) {
                  const obj = tableTitle.find((item) => item.key === field);

                  if (obj) {
                    obj.ifShow = !!selected;

                    obj.fixed = setTableTitleFn(item);

                    obj.fixedPosition = selected ? fixedPosition : 0;

                    obj.fieldOrder = fieldOrder;

                    switch (fixedPosition) {
                      case 0:
                        newTableTitle.push(obj);
                        break;
                      case 1:
                        leftTableTitle.push(obj);
                        break;
                      case 2:
                        rightTableTitle.push(obj);
                        break;
                      default:
                        newTableTitle.push(obj);
                        break;
                    }
                  }
                }
              });

            newTableTitle = [...leftTableTitle, ...newTableTitle, ...rightTableTitle];

            if (selection) newTableTitle.unshift(selection);

            if (newTableTitle.length !== tableTitle.length - 1) {
              for (const item of tableTitle) {
                const { label = '', key = '' } = item;

                if (label && key !== 'action') {
                  const obj = newTableTitle.find((lItem: any) => lItem.label === label);

                  if (!obj) {
                    item.fixed = undefined;

                    item.fixedPosition = 0;

                    newTableTitle.push(item);
                  }
                }
              }
            }

            const actionObj = newTableTitle.find((item) => item.key === 'action');

            actionObj && (actionObj.ifShow = true);

            // console.log(tableTitle);

            // console.log(newTableTitle);

            setColumns2(newTableTitle);
          }

          fieldInfoList.value = row;
        } catch (e) {
          console.log(e);
        }

        nextTick(() => {
          const view = document.querySelector(
            '.table-toolbar .n-data-table-base-table-body .n-scrollbar-container'
          );

          if (view) view.scrollLeft = 0;

          loading2.value = false;
        });
      };

      // 组装表格信息
      const getBindValues = computed(() => {
        const tableData = unref(getDataSourceRef);

        const maxHeight = getProps.value.maxHeight
          ? getProps.value.maxHeight
          : tableData.length
          ? `${unref(deviceHeight)}px`
          : undefined;

        const columns = cloneDeep(toRaw(unref(getPageColumns)));

        // const maxWidth = columns.length ?

        let maxWidth = 0;

        for (const item of columns) {
          const {
            key = null,
            render = null,
            sorter = null,
            width = null,
            minWidth = null,
          } = item as any;

          if (width) {
            maxWidth += width;
          } else if (minWidth) {
            maxWidth += minWidth;
          } else {
            item.width = 100;

            maxWidth += 100;
          }

          if (!render) {
            item.render = (row) => {
              return h('span', {
                innerText:
                  row[key] === null || row[key] === undefined || row[key] === '' ? '-' : row[key],
              });
            };
          }

          if (key !== 'action' && key !== 'selection' && sorter !== false) item.sorter = true;
        }

        // console.log(unref(getProps));

        // console.log(unref(getProps).checkedRowKeys);

        // console.log(checkedRowKeys);

        // console.log(unref(getProps).checkedRowKeyModel);
        // console.log({
        //   ...unref(getProps),
        //   'checked-row-keys': unref(getProps).checkedRowKeyModel
        //     ? unref(getProps).checkedRowKeys || []
        //     : checkedRowKeys.value || [],
        //   loading: unref(getLoading) || loading2.value,
        //   columns,
        //   rowKey: unref(getRowKey),
        //   data: tableData,
        //   size: unref(getTableSize),
        //   remote: true,
        //   'max-height': maxHeight,
        //   'scroll-x': maxWidth,
        // });
        return {
          ...unref(getProps),
          'checked-row-keys': unref(getProps).checkedRowKeyModel
            ? unref(getProps).checkedRowKeys || []
            : checkedRowKeys.value || [],
          loading: unref(getLoading) || loading2.value,
          columns,
          rowKey: unref(getRowKey),
          data: tableData,
          size: unref(getTableSize),
          remote: true,
          'max-height': maxHeight || 500,
          'scroll-x': maxWidth,
        };
      });

      // console.log(getBindValues.value)

      if (props.isGetFieldInfo && !isGetFieldInfoListFn.value) getFieldInfoListFn();

      // 获取分页信息
      const pagination: any = computed(() => {
        const obj: any = toRaw(unref(getPaginationInfo));
        const minPageSize = 10;
        const { total = 0 } = obj;

        if (total <= minPageSize) return false;

        return toRaw(unref(getPaginationInfo));
      });

      function setProps(props: Partial<BasicTableProps>) {
        innerPropsRef.value = { ...unref(innerPropsRef), ...props };
      }

      const tableAction = {
        reload,
        setColumns,
        setLoading,
        setProps,
        getColumns,
        getPageColumns,
        getCacheColumns,
        setCacheColumnsField,
        emit,
        setEditTableDataFn,
        getEditTableDataFn,
      };

      const getCanResize = computed(() => {
        const { canResize } = unref(getProps);
        return canResize;
      });

      async function computeTableHeight() {
        const table = unref(tableElRef);
        if (!table) return;
        if (!unref(getCanResize)) return;
        const tableEl: any = table?.$el;
        const headEl = tableEl.querySelector('.n-data-table-thead ');
        const { bottomIncludeBody } = getViewportOffset(headEl);
        const headerH = 64;
        let paginationH = 2;
        const marginH = 24;
        if (!isBoolean(pagination)) {
          paginationEl = tableEl.querySelector('.n-data-table__pagination') as HTMLElement;
          if (paginationEl) {
            const offsetHeight = paginationEl.offsetHeight;
            paginationH += offsetHeight || 0;
          } else {
            paginationH += 28;
          }
        }
        let height =
          bottomIncludeBody - (headerH + paginationH + marginH + (props.resizeHeightOffset || 0));
        const maxHeight = props.maxHeight;
        height = maxHeight && maxHeight < height ? maxHeight : height;
        deviceHeight.value = height;
      }

      useWindowSizeFn(computeTableHeight, 280);

      onMounted(() => {
        nextTick(() => {
          computeTableHeight();
        });
      });

      // const tableContext: any = ;

      createTableContext({ ...tableAction, wrapRef, getBindValues });

      // console.log(tableContext);

      const permissionFn = (action) => {
        const { prop = '', hump = false, auth = '', unAuth = false } = action;

        if (unAuth) return {};

        if (prop || auth) {
          const list: any = [];

          if (prop) {
            list.push(
              `${authCode}${
                hump ? prop.slice(0, 1).toUpperCase() + prop.slice(1).toLowerCase() : `-${prop}`
              }`
            );
          }

          if (auth) list.push(auth);

          // console.log(list);

          return { action: list };
        }
      };

      const handleCheckedRowKeysChangeFn = (rowKeys: any = []) => {
        // console.log(getBindValues.value);
        if (getBindValues.value['onUpdate:checkedRowKeys']) {
          getBindValues.value['onUpdate:checkedRowKeys'](rowKeys);
        } else {
          // console.log(rowKeys);
          checkedRowKeys.value = rowKeys || [];
        }
      };

      watch(
        checkedRowKeys,
        (val) => {
          emit('updateCheck', toRaw(val));
        },
        {
          immediate: false,
        }
      );

      const tableOperaColumn = computed(() => {
        const { operaColumn = [], isEditTable = false, showAddAndDelBtn = true } = props;

        const newOperaColumn: any = [];
        // console.log('arg,arg', operaColumn);
        if (isEditTable && showAddAndDelBtn && routerType !== 'check') {
          return [
            {
              label: 'add',
              prop: 'add',
              unAuth: true,
              bind: {
                type: 'primary',
                'on-click': () => {
                  editTableHandleAddFn((editTableData) => {
                    emit('editTableDataChangeFn',editTableData)
                  });
                },
              },
            },
            {
              label: 'delete',
              prop: 'delete',
              unAuth: true,
              bind: {
                disabled: !checkedRowKeys.value.length,
                'on-click': () => {
                  editTableHandleDeleteFn(toRaw(checkedRowKeys.value),(editTableData) => {
                    emit('editTableDataChangeFn',editTableData)
                  });
                },
              },
            },
          ];
        }

        // console.log(operaColumn);

        if (operaColumn && operaColumn.length) {
          for (const item of operaColumn) {
            // console.log('operaColumn', operaColumn, permissionFn(item)?.action);
            if (hasPermission(permissionFn(item)?.action)) newOperaColumn.push(item);
          }
        }
        // console.log('newOperaColumn', newOperaColumn);
        return newOperaColumn || [];
      });

      return {
        ...toRefs(state),
        tableElRef,
        getBindValues,
        getDataSource,
        setTableData,
        densityOptions,
        reload,
        densitySelect,
        updatePage,
        updatePageSize,
        // updatePageNum,
        pagination,
        tableAction,
        permissionFn,
        handleSorterChange,
        checkedRowKeys,
        clearRowKeysFn,
        clearCheckedRowKeysFn,
        // importImg,
        // exportImg,
        fixedModal,
        tableContext,
        getFieldInfoListFn,
        handleCheckedRowKeysChangeFn,
        tableOperaColumn,
        getEditTableDataFn,
        setEditTableDataFn,
        setEditTableAllDataFn,
      };
    },
  };
</script>

<style lang="less" scoped>
  .table-toolbar {
    display: flex;
    justify-content: space-between;
    padding: 0 0 16px 0;

    &-left {
      display: flex;
      align-items: center;
      justify-content: flex-start;
      flex: 1;

      &-title {
        display: flex;
        align-items: center;
        justify-content: flex-start;
        font-size: 16px;
        font-weight: 600;
      }
    }

    &-right {
      display: flex;
      justify-content: flex-end;
      // flex: 1;

      &-icon {
        margin-left: 12px;
        font-size: 16px;
        cursor: pointer;
        color: var(--text-color);

        :hover {
          color: #307AFA;
        }
      }
    }
  }

  .table-toolbar-inner-popover-title {
    padding: 2px 0;
  }
  :deep(.n-data-table .n-data-table-th .n-data-table-th__title-wrapper .n-data-table-th__title) {
    display: flex;
    flex: none;
    min-width: 0;
    .tableTip {
      color: #f5222d;
      margin-right: 3px;
      font-size: 16px;
      font-weight: 400;
    }
  }
  .btn-list {
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
  }
  .active-img {
    padding-top: 3px;
  }
  :deep(.n-data-table .n-data-table__pagination) {
    min-width: 715px !important;
  }

  .print-svg {
    width: 16px;
  }
</style>

<style lang="less">
  .n-popover__content {
    max-width: 600px !important;
  }
  .bnt-list {
    padding-top: 1px !important;
  }

  .s-table {
    .n-data-table-table {
      .n-data-table-tbody {
        tr {
          td:nth-of-type(1):not(.n-data-table-td--selection):not(.n-data-table-td--fixed-left):not([data-col-key='index']) {
            display: flex;
            align-items: center;
            span {
              width: 200px;
              vertical-align: bottom;
            }
          }
        }
      }
    }
  }
</style>
